package org.springblade.modules.item.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.gg.reader.api.dal.GClient;
import com.gg.reader.api.dal.HandlerTagEpcLog;
import com.gg.reader.api.dal.HandlerTagEpcOver;
import com.gg.reader.api.protocol.gx.*;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.modules.item.entity.ItemEntity;
import org.springblade.modules.item.service.IItemService;
import org.springblade.modules.item.service.RfidService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

import static org.springblade.common.constant.RedisKeyConstant.RFID_KEY_EXPIRE;
import static org.springblade.common.constant.RedisKeyConstant.RFID_KEY_PREFIX;


@Service
@Slf4j
public class RfidServiceImpl implements RfidService {
	@Autowired
	private BladeRedis bladeRedis;
	@Value("${rfid.readName}")
	private String readName;
	@Value("${rfid.timeout}")
	private int timeout;

	@Autowired
	private IItemService itemService;

	@Override
	public void tcpReadTag( ) {
		 GClient client = new GClient();
		//readName:读取的tcp的ip地址，timeout：读取间隔（毫秒）
		if (client.openTcp(readName, timeout)) {
			// 订阅标签上报事件
			client.onTagEpcLog = new HandlerTagEpcLog() {
				@Override
				public void log(String readName, LogBaseEpcInfo logBaseEpcInfo) {
					// 回调内部如有阻塞，会影响API正常使用
					// 标签回调数量较多，请将标签数据先缓存起来再作业务处理
					if (null != logBaseEpcInfo && 0 == logBaseEpcInfo.getResult()) {
						log.info(logBaseEpcInfo.toString());
					}
				}
			};
//


			// 功率配置, 将4个天线功率都设置为30dBm.
			//todo 持久化配置，断电保存 ，请勿做重复配置操作，需要频繁配置时，请先查询校验
			//MsgBaseSetPower msgBaseSetPower = new MsgBaseSetPower();
			//Hashtable<Integer, Integer> hashtable = new Hashtable<>();
			//hashtable.put(1, 30);
			//hashtable.put(2, 30);
			//hashtable.put(3, 30);
			//hashtable.put(4, 30);
			//msgBaseSetPower.setDicPower(hashtable);
			//client.sendSynMsg(msgBaseSetPower);
			//if (0 == msgBaseSetPower.getRtCode()) {
			//    System.out.println("Power configuration successful.");
			//} else {
			//    System.out.println("Power configuration error.");
			//}

			log.info("开始订阅标签信息");

			// 4个天线读卡, 读取EPC数据区以及TID数据区
			MsgBaseInventoryEpc msgBaseInventoryEpc = new MsgBaseInventoryEpc();
            msgBaseInventoryEpc.setAntennaEnable(EnumG.AntennaNo_1 | EnumG.AntennaNo_2 | EnumG.AntennaNo_3 | EnumG.AntennaNo_4);
//			msgBaseInventoryEpc.setAntennaEnable(EnumG.AntennaNo_1);
			msgBaseInventoryEpc.setInventoryMode(EnumG.InventoryMode_Inventory);//连续
			ParamEpcReadTid tid = new ParamEpcReadTid();
			tid.setMode(EnumG.ParamTidMode_Auto);
			tid.setLen(6);
			msgBaseInventoryEpc.setReadTid(tid);

			client.sendSynMsg(msgBaseInventoryEpc);
			if (0 == msgBaseInventoryEpc.getRtCode()) {
				log.info("Inventory epc successful.");
			} else {
				log.info("Inventory epc error.");
			}


		} else {
			log.info("Connect failure.");
		}
	}

	@Override
	public void onTagEpcOver(GClient gClient) {
		MsgBaseStop msgBaseStop = new MsgBaseStop();
		// 停止读卡，空闲态
		gClient.sendSynMsg(msgBaseStop);
		if (0 == msgBaseStop.getRtCode()) {
			log.info("停止读卡成功");
		} else {
			log.info("Stop error.");
		}
		gClient.onTagEpcOver = new HandlerTagEpcOver() {
			@Override
			public void log(String readName, LogBaseEpcOver logBaseEpcOver) {
				if (null != logBaseEpcOver) {
					log.info("Epc log over.");
				}
			}
		};
		gClient.close();
	}


	/**
	 * 定时任务 标签读取
	 */
	public void tcpReadTagTask() {
		GClient client = new GClient();
		Map<String,LogBaseEpcInfo> map=new ConcurrentHashMap<>();
		AtomicBoolean flag=new AtomicBoolean(false);
		//readName:读取的tcp的ip地址，timeout：读取间隔（毫秒）
		if (client.openTcp(readName, timeout)) {
			// 订阅标签上报事件
			client.onTagEpcLog = new HandlerTagEpcLog() {
				@Override
				public void log(String readName, LogBaseEpcInfo logBaseEpcInfo) {
					// 回调内部如有阻塞，会影响API正常使用
					// 标签回调数量较多，请将标签数据先缓存起来再作业务处理
					if (null != logBaseEpcInfo && 0 == logBaseEpcInfo.getResult()) {
						String tid = logBaseEpcInfo.getTid();
						String epc = logBaseEpcInfo.getEpc();
						if (!map.containsKey(tid)){
							map.put(tid,logBaseEpcInfo);
						}else {//出现重复的元素，表示所有标签已经遍历过一遍了
							log.info("订阅完成，关闭订阅......");
							MsgBaseStop msgBaseStop = new MsgBaseStop();
							// 停止读卡，空闲态
							client.sendSynMsg(msgBaseStop);
							//关闭连接
							client.close();
							flag.set(true);
						}

					}
				}
			};

			log.info("开始订阅标签信息");

			// 4个天线读卡, 读取EPC数据区以及TID数据区
			MsgBaseInventoryEpc msgBaseInventoryEpc = new MsgBaseInventoryEpc();
//			msgBaseInventoryEpc.setAntennaEnable(EnumG.AntennaNo_1);
			msgBaseInventoryEpc.setAntennaEnable(EnumG.AntennaNo_1 | EnumG.AntennaNo_2 | EnumG.AntennaNo_3 | EnumG.AntennaNo_4);
			msgBaseInventoryEpc.setInventoryMode(EnumG.InventoryMode_Inventory);

			//必须要TID
			ParamEpcReadTid paramEpcReadTid = new ParamEpcReadTid();
			paramEpcReadTid.setMode(EnumG.ParamTidMode_Auto);
			paramEpcReadTid.setLen(6);
			msgBaseInventoryEpc.setReadTid(paramEpcReadTid);

			client.sendSynMsg(msgBaseInventoryEpc);
			if (0 == msgBaseInventoryEpc.getRtCode()) {
				log.info("Inventory epc successful.");
			} else {
				log.info("Inventory epc error.");
			}

			while (!flag.get()){
				log.info("当前标签数量:{}",map.size());
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			bladeRedis.setEx(RFID_KEY_PREFIX , map, RFID_KEY_EXPIRE);

			Set<String> keySet = map.keySet();
			List<String> itemEntityList = itemService.list(Wrappers.<ItemEntity>query().lambda()
				.in(ItemEntity::getTid,keySet)).stream().map(ItemEntity::getTid).collect(Collectors.toList());
			keySet.forEach(key->{
				if (!itemEntityList.contains(key)) {//把不存在数据库中的便签 新建一条数据
					ItemEntity itemEntity=new ItemEntity();
					itemEntity.setRfidManage(1);
					itemEntity.setEpc(map.get(key).getEpc());
					itemEntity.setTid(key);
					itemEntity.setItemName(key);
					itemEntity.setStock(1);
					itemEntity.setTotal(1);
					itemService.save(itemEntity);
				}
			});

		} else {
			log.info("连接失败");
		}
	}
}
